package dependency

import (
	"errors"
	"fmt"
	"sort"

	"github.com/Masterminds/semver/v3"
)

// Plugin 表示插件
type Plugin struct {
	// ID 是插件ID
	ID string
	// Version 是插件版本
	Version string
	// Dependencies 是插件依赖
	Dependencies map[string]string
}

// DependencyGraph 表示依赖图
type DependencyGraph struct {
	// nodes 是节点映射表
	nodes map[string]*Node
}

// Node 表示依赖图节点
type Node struct {
	// Plugin 是插件
	Plugin *Plugin
	// Dependencies 是依赖节点列表
	Dependencies []*Node
	// Dependents 是被依赖节点列表
	Dependents []*Node
	// Visited 是访问标志
	Visited bool
	// Temporary 是临时标志，用于检测循环依赖
	Temporary bool
}

// NewDependencyGraph 创建一个新的依赖图
func NewDependencyGraph() *DependencyGraph {
	return &DependencyGraph{
		nodes: make(map[string]*Node),
	}
}

// AddPlugin 添加插件
func (g *DependencyGraph) AddPlugin(plugin *Plugin) {
	// 创建节点ID
	nodeID := fmt.Sprintf("%s@%s", plugin.ID, plugin.Version)

	// 检查节点是否已存在
	if _, ok := g.nodes[nodeID]; ok {
		return
	}

	// 创建节点
	node := &Node{
		Plugin:       plugin,
		Dependencies: make([]*Node, 0),
		Dependents:   make([]*Node, 0),
		Visited:      false,
		Temporary:    false,
	}
	g.nodes[nodeID] = node
}

// AddDependency 添加依赖
func (g *DependencyGraph) AddDependency(plugin *Plugin, dependency *Plugin) {
	// 创建节点ID
	pluginNodeID := fmt.Sprintf("%s@%s", plugin.ID, plugin.Version)
	dependencyNodeID := fmt.Sprintf("%s@%s", dependency.ID, dependency.Version)

	// 获取节点
	pluginNode, ok := g.nodes[pluginNodeID]
	if !ok {
		return
	}
	dependencyNode, ok := g.nodes[dependencyNodeID]
	if !ok {
		return
	}

	// 添加依赖
	pluginNode.Dependencies = append(pluginNode.Dependencies, dependencyNode)
	dependencyNode.Dependents = append(dependencyNode.Dependents, pluginNode)
}

// GetNode 获取节点
func (g *DependencyGraph) GetNode(id, version string) (*Node, bool) {
	nodeID := fmt.Sprintf("%s@%s", id, version)
	node, ok := g.nodes[nodeID]
	return node, ok
}

// GetAllNodes 获取所有节点
func (g *DependencyGraph) GetAllNodes() []*Node {
	nodes := make([]*Node, 0, len(g.nodes))
	for _, node := range g.nodes {
		nodes = append(nodes, node)
	}
	return nodes
}

// DetectCycles 检测循环依赖
func (g *DependencyGraph) DetectCycles() ([][]*Plugin, error) {
	// 重置标志
	for _, node := range g.nodes {
		node.Visited = false
		node.Temporary = false
	}

	// 检测循环
	cycles := make([][]*Plugin, 0)
	for _, node := range g.nodes {
		if !node.Visited {
			cycle := make([]*Plugin, 0)
			err := g.visit(node, &cycle)
			if err != nil {
				cycles = append(cycles, cycle)
			}
		}
	}

	if len(cycles) > 0 {
		return cycles, errors.New("circular dependencies detected")
	}
	return nil, nil
}

// visit 访问节点
func (g *DependencyGraph) visit(node *Node, cycle *[]*Plugin) error {
	// 检查是否已访问
	if node.Visited {
		return nil
	}

	// 检查是否有循环
	if node.Temporary {
		*cycle = append(*cycle, node.Plugin)
		return errors.New("circular dependency detected")
	}

	// 标记为临时访问
	node.Temporary = true
	*cycle = append(*cycle, node.Plugin)

	// 访问依赖
	for _, dep := range node.Dependencies {
		err := g.visit(dep, cycle)
		if err != nil {
			return err
		}
	}

	// 标记为已访问
	node.Temporary = false
	node.Visited = true
	*cycle = (*cycle)[:len(*cycle)-1]

	return nil
}

// TopologicalSort 拓扑排序
func (g *DependencyGraph) TopologicalSort() ([]*Plugin, error) {
	// 检测循环依赖
	cycles, err := g.DetectCycles()
	if err != nil {
		return nil, fmt.Errorf("failed to sort dependencies: %w", err)
	}
	if len(cycles) > 0 {
		return nil, fmt.Errorf("circular dependencies detected")
	}

	// 重置标志
	for _, node := range g.nodes {
		node.Visited = false
	}

	// 排序
	sorted := make([]*Plugin, 0, len(g.nodes))
	for _, node := range g.nodes {
		if !node.Visited {
			g.topologicalSortVisit(node, &sorted)
		}
	}

	// 反转结果
	for i, j := 0, len(sorted)-1; i < j; i, j = i+1, j-1 {
		sorted[i], sorted[j] = sorted[j], sorted[i]
	}

	return sorted, nil
}

// topologicalSortVisit 拓扑排序访问
func (g *DependencyGraph) topologicalSortVisit(node *Node, sorted *[]*Plugin) {
	// 检查是否已访问
	if node.Visited {
		return
	}

	// 标记为已访问
	node.Visited = true

	// 访问依赖
	for _, dep := range node.Dependencies {
		g.topologicalSortVisit(dep, sorted)
	}

	// 添加到结果
	*sorted = append(*sorted, node.Plugin)
}

// DependencyResolver 表示依赖解析器
type DependencyResolver struct {
	// plugins 是插件映射表
	plugins map[string][]*Plugin
}

// NewDependencyResolver 创建一个新的依赖解析器
func NewDependencyResolver() *DependencyResolver {
	return &DependencyResolver{
		plugins: make(map[string][]*Plugin),
	}
}

// AddPlugin 添加插件
func (r *DependencyResolver) AddPlugin(plugin *Plugin) {
	// 检查插件是否已存在
	versions, ok := r.plugins[plugin.ID]
	if !ok {
		versions = make([]*Plugin, 0)
	}

	// 检查版本是否已存在
	for _, v := range versions {
		if v.Version == plugin.Version {
			return
		}
	}

	// 添加插件
	versions = append(versions, plugin)
	r.plugins[plugin.ID] = versions
}

// GetPlugin 获取插件
func (r *DependencyResolver) GetPlugin(id, version string) (*Plugin, error) {
	// 检查插件是否存在
	versions, ok := r.plugins[id]
	if !ok {
		return nil, fmt.Errorf("plugin %s not found", id)
	}

	// 查找版本
	for _, v := range versions {
		if v.Version == version {
			return v, nil
		}
	}

	return nil, fmt.Errorf("plugin %s version %s not found", id, version)
}

// ResolveVersionConstraint 解析版本约束
func (r *DependencyResolver) ResolveVersionConstraint(id, constraint string) (string, error) {
	// 检查插件是否存在
	versions, ok := r.plugins[id]
	if !ok {
		return "", fmt.Errorf("plugin %s not found", id)
	}

	if len(versions) == 0 {
		return "", fmt.Errorf("no versions found for plugin %s", id)
	}

	// 解析约束
	c, err := semver.NewConstraint(constraint)
	if err != nil {
		return "", fmt.Errorf("invalid constraint %s: %w", constraint, err)
	}

	// 解析版本
	semvers := make([]*semver.Version, 0)
	versionMap := make(map[string]*Plugin)
	for _, v := range versions {
		sv, err := semver.NewVersion(v.Version)
		if err != nil {
			return "", fmt.Errorf("invalid version %s for plugin %s: %w", v.Version, id, err)
		}
		// 检查约束
		if c.Check(sv) {
			semvers = append(semvers, sv)
			versionMap[sv.String()] = v
		}
	}

	if len(semvers) == 0 {
		return "", fmt.Errorf("no version satisfies constraint %s for plugin %s", constraint, id)
	}

	// 排序版本
	sort.Sort(sort.Reverse(semver.Collection(semvers)))

	// 返回最新版本
	return semvers[0].String(), nil
}

// ResolveDependencies 解析依赖
func (r *DependencyResolver) ResolveDependencies(id, version string) ([]*Plugin, error) {
	// 获取插件
	plugin, err := r.GetPlugin(id, version)
	if err != nil {
		return nil, fmt.Errorf("failed to get plugin: %w", err)
	}

	// 创建依赖图
	graph := NewDependencyGraph()
	graph.AddPlugin(plugin)

	// 解析依赖
	err = r.resolveDependenciesRecursive(plugin, graph)
	if err != nil {
		return nil, fmt.Errorf("failed to resolve dependencies: %w", err)
	}

	// 拓扑排序
	sorted, err := graph.TopologicalSort()
	if err != nil {
		return nil, fmt.Errorf("failed to sort dependencies: %w", err)
	}

	return sorted, nil
}

// resolveDependenciesRecursive 递归解析依赖
func (r *DependencyResolver) resolveDependenciesRecursive(plugin *Plugin, graph *DependencyGraph) error {
	// 解析依赖
	for depID, constraint := range plugin.Dependencies {
		// 解析版本约束
		version, err := r.ResolveVersionConstraint(depID, constraint)
		if err != nil {
			return fmt.Errorf("failed to resolve dependency %s: %w", depID, err)
		}

		// 获取依赖插件
		dep, err := r.GetPlugin(depID, version)
		if err != nil {
			return fmt.Errorf("failed to get dependency %s: %w", depID, err)
		}

		// 添加依赖
		graph.AddPlugin(dep)
		graph.AddDependency(plugin, dep)

		// 递归解析依赖
		err = r.resolveDependenciesRecursive(dep, graph)
		if err != nil {
			return err
		}
	}

	return nil
}

// ValidateDependencies 验证依赖
func (r *DependencyResolver) ValidateDependencies(id, version string) error {
	// 解析依赖
	_, err := r.ResolveDependencies(id, version)
	return err
}
